﻿/*******************************************************************************
 * 
 *Author         :  VN
 *Description    :  多线程接收网络回包
 *Other          :  None
 *Modify Record  :  2015/7/6
 *
*******************************************************************************/
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System;
using System.IO;
using UnityEngine;
using cs;

namespace Network
{
    class ReceiverThread : NetThread
    {
        const uint MAX_LEN_CLI_PKG_DATA = 65536;
        private const uint m_MinPacketSize = 8;

        private byte[] m_RecBuf;
        private int    m_RecBufOffset;
        private Queue  m_ThreadSafeQueue;
        
        public delegate void CallbackRecvReply(Queue quePack);
        private CallbackRecvReply OnRecvReply = null;
        public CallbackRecvReply  RecvReply
        {
            get
            {
                return OnRecvReply;
            }
            set
            {
                OnRecvReply = value;
            }
        }

        public ReceiverThread(NetworkStream stream) : base(stream)
        {
            m_RecBufOffset = 0;
            m_RecBuf = new byte[MAX_LEN_CLI_PKG_DATA];
            m_ThreadSafeQueue = Queue.Synchronized(new Queue());
        }

        /*************************************************
        Description : 线程的主函数
        Input       : none
        Output      : none
        Return      : none
        Others      : none
        *************************************************/
        protected override void Main()
        {
            if (RunMode.Instance.LogNetwork) Debug.Log("ReceiverThread.Main : Begin");
            while (!IsTerminateFlagSet())
            {
                ReadFromStream();
                ScanPackets();
                ProcPackets();
            }
            if (RunMode.Instance.LogNetwork) Debug.Log("ReceiverThread.Main : End");
        }

        /*************************************************
        Description : 从网络流读取
        Input       : none
        Output      : none
        Return      : none
        Others      : none
        *************************************************/
        protected void ReadFromStream()
        {
            if (NetStream.DataAvailable)
            {
                m_RecBufOffset += NetStream.Read(m_RecBuf, m_RecBufOffset, m_RecBuf.Length - m_RecBufOffset);
            }
            else
            {
                Thread.Sleep(15);
            }
        }

        /*************************************************
        Description : 扫描收到的包,并解出包体放入解析队列
        Input       : none
        Output      : none
        Return      : none
        Others      : none
        *************************************************/
        protected void ScanPackets()
        {
            while (m_RecBufOffset >= m_MinPacketSize && !IsTerminateFlagSet())
            {
                int dwPkgLen = (int)BitConverter.ToInt32(m_RecBuf, 0);
                dwPkgLen = IPAddress.NetworkToHostOrder(dwPkgLen);

                if (dwPkgLen+4 > MAX_LEN_CLI_PKG_DATA)  //不能超过
                {
                    m_RecBufOffset = 0;
                    if (RunMode.Instance.LogNetwork) Debug.LogWarning("dwPkgLen:" + dwPkgLen + ", max length:" + MAX_LEN_CLI_PKG_DATA);
                    break;
                }

                if (m_RecBufOffset < dwPkgLen + 4)
                {
                    if (RunMode.Instance.LogNetwork) Debug.LogWarning("m_RecBufOffset:" + m_RecBufOffset + ", pkg length:" + dwPkgLen);
                    break;
                }

                byte[] Buf = new byte[dwPkgLen];
                Array.Copy(m_RecBuf, 4, Buf, 0, dwPkgLen);
                m_ThreadSafeQueue.Enqueue(Buf);

                int offset = dwPkgLen + 4;
                if (m_RecBufOffset > offset)
                {
                    Array.Copy(m_RecBuf, offset, m_RecBuf, 0, m_RecBufOffset - offset);
                    m_RecBufOffset -= offset;
                }
                else
                {
                    m_RecBufOffset = 0;
                }
            }
        }

        /*************************************************
        Description : 处理收包
        Input       : none
        Output      : none
        Return      : none
        Others      : none
        *************************************************/
        protected void ProcPackets()
        {
            if (OnRecvReply != null && m_ThreadSafeQueue.Count > 0)
            {
                lock (m_ThreadSafeQueue)
                {
                    OnRecvReply(m_ThreadSafeQueue);
                }
            }
        }
    }
}